package net.doglog;

import java.util.*;
import javax.jdo.annotations.*;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Text;

/**
 * This is the most important class for blogs are to serve posts. 
 * Post entities are stored in the database and are operated via 
 * the standard JDO API to some extent.
 * 
 * *** about defaultFetchGroup:
 * http://www.datanucleus.org/products/accessplatform_1_1/jdo/fetchgroup.html#dfg
 * 
 * @author oipn4e2
 *
 */
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class Post {
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key = null;
	
	public Key getKey() {
		return key;
	}
	
	public long getId() {
		return key.getId();
	}

	public Post() {
		this.time = System.currentTimeMillis();
	}
	
	@Persistent
	private long time;
	
	public long getTime() {
		return time;
	}
	
	/**
	 * Post title stored in escaped form.
	 * @see net.doglog.BlogUtil#escapeTag
	 */
	@Persistent
	private String title;

	public void setTitle(String title) {
		this.title = BlogUtil.escapeTag(title);
	}
	
	public String getTitle() {
		return title;
	}
	
	/**
	 * Post tags stored in a Set. This field may be null.
	 * @see getTags
	 */
	@Persistent(defaultFetchGroup = "true")
	private Set<String> tags;
	
	/**
	 * Tags are escaped here.
	 * @param tag
	 * @return operation result (true if added)
	 */
	public boolean addTag(String tag) {
		if (tag == null) return false;
		tag = tag.trim();
		if (tag.length() == 0) return false;
		tag = BlogUtil.escapeTag(tag.toLowerCase());
		if (tags == null)
			tags = new HashSet<String>();
		return tags.add(tag);
	}
	
	public void clearTags() {
		tags = new HashSet<String>();
	}
	
	/**
	 * @return post tags in a unmidifiableSet
	 */
	public Set<String> getTags() {
		if (tags == null)
			tags = new HashSet<String>();
		return Collections.unmodifiableSet(tags);
	}
	
	/**
	 * Post content stored in a Text. GAE doesn't support 
	 * long String, so we use this. Post content is not escaped, 
	 * so HTML codes is allowed.
	 */
	@Persistent(defaultFetchGroup = "true")
	private Text content;
	
	public void setContent(String content) {
		this.content = new Text(content);
	}
	
	public String getContent() {
		return content.getValue();
	}
	
	/**
	 * Save a post using transaction.
	 * @see net.doglog.PostUtil#savePost(Post)
	 * @return operation result (true if succeed)
	 */
	public boolean save() {
		return PostUtil.savePost(this);
	}
	
	@Persistent(defaultFetchGroup = "true")
	@Order(extensions = @Extension(vendorName="datanucleus", key="list-ordering", value="time asc"))
	private List<Comment> comments;
	
	public List<Comment> getComments() {
		if (comments == null)
			comments = new ArrayList<Comment>();
		return comments;
	}
}
